package cn.com.ursaminor.mysql4j.core;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.JdbcTemplate;

import cn.com.ursaminor.mysql4j.util.Mysql4jUtil;

/**
 * 该类定义一个实体表，所有配置类，需要继承此类.
 * 
 * <p>该类管理封装数据的pojo/Row类（class）、主键以及当前表所有字段的列表.</p>
 * <p>pojo类是一个普通的JavaBean，用来装载数据，Row为Mysql4J提供的一个Map，可用来替代pojo.</p>
 * <p>主键是一个{@link Column}对象，目前不支持多字段的复合主键.</p>
 * <p>字段列表用来构建那些需要列出全部字段的sql，该列表根据配置类属性自动生成.</p>
 * 
 * @author 小熊
 * @version 1.0
 */
public class Table extends AbstTable
{
	Class pojo;					// 数据模型对象
	Column primaryKey;			// 主键
	List<Column> columns;		// 所有字段
	
	/**
	 *	构造方法，由继承Table的配置类调用.
	 *
	 *	@param pojo 数据装载类，可为pojo的class或者Row的class
	 */
	protected Table(Class pojo)
	{
		super();
		this.pojo = pojo;
	}
	
	/**
	 *	表名，继承的配置类的类名需要和表名保持一致.
	 *
	 *  <p>表名同类名一致，可以使配置类在使用时，以表的形式出现，增加代码的可读性.</p>
	 *
	 *  @return 表名，同时也是当前类名（simple name）
	 */
	public String getName()
	{
		return this.getClass().getSimpleName();
	}
	
	// 全称，形式为 表名 as 表别名
	public String getString()
	{
		return this.getClass().getSimpleName() + " " + getAlias();
	}
	
	/**
	 *	配置类构造方法中，需要调用此方法，此方法是setJdbcTemplate(jdbcTemplate)和init()两个方法的顺序调用.
	 *
	 *	@param jdbcTemplate JdbcTemplate对象
	 */
	protected void init(JdbcTemplate jdbcTemplate)
	{
		setJdbcTemplate(jdbcTemplate);
		init();
	}

	/**
	 *	该方法初始化配置类的属性等，配置类构造方法中，需要调用此方法.
	 */
	protected void init()
	{
		columns = new ArrayList<>();
		Field[] fs = getClass().getDeclaredFields();
		for(Field f : fs)
		{
			try
			{
				String modifier = Modifier.toString(f.getModifiers());
				if(!modifier.contains("public")) continue;
				
				if(Column.class.isAssignableFrom(f.getType()))
				{
					f.setAccessible(true);
					Column c = (Column)f.get(this);
					if(c==null)
					{
						c = (Column)f.getType().newInstance();
						f.set(this, c);
					}
					
					c.name = f.getName();
					c.table = this;
					if(c.pk) this.primaryKey = c;
					
					columns.add(c);
					
					if(!Map.class.isAssignableFrom(pojo))	// _pojo is not a Map
					{
						try
						{
							if(c.property==null || c.property.length()==0) c.property = getProperty(c.name);
							String m = "get"+Mysql4jUtil.initialUpperCase(c.property);
							c.method = pojo.getMethod(m, new Class[0]);
						}
						catch(Exception e)
						{
							c.property = null;
							c.method = null;
						}
					}
				}
			}
			catch(Exception e)
			{
				System.out.println(e);
			}
		}
	}
	
	// 根据列名返回pojo属性
	private String getProperty(String column)
	{
		column = column.toLowerCase();
		if(column.indexOf('_')<0) return column;
		
		String[] cc = column.split("_");
		String p = cc[0];
		for(int i=1; i<cc.length; i++)
		{
			p += cc[i].substring(0,1).toUpperCase()+cc[i].substring(1);
		}
		return p;
	}
}